/* 
 * imagentheaders/callback.cpp
 * Written by, Sohail Qayum Malik[sqm@hackers.pk]
 */

/* For debuging purposes, should be gone when done */
#include <iostream>
/*  For debugging purposes ends here */

#include <stdio.h>  
#include "callback.h"

int callback_imagentheaders(int argc, ...) { 
 
   int ret = 0;  
   size_t size = 0;
   void *ptr = NULL;   
   va_list VList;
   
   struct epoch_ty epoch_ty_instance;
   
   PIMAGE_DOS_HEADER dosheader = NULL; 
   PIMAGE_FILE_HEADER fileheader = NULL; 
   PIMAGE_OPTIONAL_HEADER optionalheader = NULL;
   //IMAGE_NT_HEADERS, which is defined in WINNT.H. This structure is composed of a DWORD and two substructures and is laid out as follows
   /* DWORD Signature;
      IMAGE_FILE_HEADER FileHeader;
      IMAGE_OPTIONAL_HEADER32/64 OptionalHeader; */
#ifdef _WIN64   
   PIMAGE_NT_HEADERS64 ntheader = NULL;
#else   
   PIMAGE_NT_HEADERS32 ntheader = NULL;
#endif       

   va_start(VList, argc);
   
   dosheader = va_arg(VList, PIMAGE_DOS_HEADER);
   
#ifdef _WIN64   
   ntheader = va_arg(VList, PIMAGE_NT_HEADERS64);
#else   
   ntheader = va_arg(VList, PIMAGE_NT_HEADERS32);
#endif   

   size = va_arg(VList, size_t);
   
   ptr = va_arg(VList, void *);
      
   va_end(VList);
   
   fileheader = &ntheader->FileHeader;
   optionalheader = &ntheader->OptionalHeader;
   
 #ifdef _WIN64   
   std::cout<<"\ntypedef struct _IMAGE_NT_HEADERS64 {"<<std::endl;
#else
   std::cout<<"\ntypedef struct _IMAGE_NT_HEADERS {"<<std::endl;
#endif
   std::cout<<"\tDWORD Signature\n\tIMAGE_FILE_HEADER FileHeader;"<<std::endl;
#ifdef _WIN64
   std::cout<<"\tIMAGE_OPTIONAL_HEADER64 OptionalHeader;"<<std::endl;
   std::cout<<"} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;"<<std::endl;
#else
   std::cout<<"\tIMAGE_OPTIONAL_HEADER32 OptionalHeader;"<<std::endl;
   std::cout<<"} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;"<<std::endl;
#endif

   std::cout<<std::endl<<"Signature = 0x"<<std::hex<<ntheader->Signature;
   
   if ( ntheader->Signature == IMAGE_NT_SIGNATURE ) {
   
      std::cout<<"(IMAGE_NT_SIGNATURE)";
   }
   else {
   
      std::cout<<"()";
   }

   std::cout<<"\n\nIMAGE_FILE_HEADER"<<std::endl;
   std::cout<<"--------------------"<<std::endl;
   
   std::cout<<"Machine              = ";   
   switch( fileheader->Machine ) {
   
      case IMAGE_FILE_MACHINE_I386:
	     std::cout<<"IMAGE_FILE_MACHINE_I386"<<std::endl;
	  break;
	  case IMAGE_FILE_MACHINE_IA64:
	     std::cout<<"IMAGE_FILE_MACHINE_IA64"<<std::endl;
	  break;
      case IMAGE_FILE_MACHINE_UNKNOWN:
	     std::cout<<"IMAGE_FILE_MACHINE_UNKNOWN"<<std::endl;
	  break;
	  default:
	     std::cout<<std::endl;
	  break;
   }
   std::cout<<"NumberOfSections     = "<<std::dec<<fileheader->NumberOfSections<<std::endl;
   //This field holds the number of seconds since December 31st, 1969, 1t 4:00 P.M. 
   epoch_ty_instance = epoch(fileheader->TimeDateStamp);   
   std::cout<<"TimeDateStamp        = "<<std::dec<<fileheader->TimeDateStamp;
   std::cout<<"("<<epoch_ty_instance.day<<"-"<<epoch_ty_instance.month<<"-"<<epoch_ty_instance.centuary<<")"<<std::endl;   
   std::cout<<"PointerToSymbolTable = 0x"<<std::hex<<fileheader->PointerToSymbolTable<<std::endl;
   std::cout<<"NumberOfSymbols      = "<<std::dec<<fileheader->NumberOfSymbols<<std::endl;
   std::cout<<"SizeOfOptionalHeader = "<<std::dec<<fileheader->SizeOfOptionalHeader<<std::endl;
   std::cout<<"Characteristics      = 0x"<<std::hex<<fileheader->Characteristics<<"(";
   
   if ( fileheader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED ) {
   
      std::cout<<"IMAGE_FILE_RELOCS_STRIPPED,";
   }
   
   if ( fileheader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE ) {
   
      std::cout<<"IMAGE_FILE_EXECUTABLE_IMAGE,";
   }
   
   if ( fileheader->Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED ) {
   
      std::cout<<"IMAGE_FILE_LINE_NUMS_STRIPPED,";
   }
   
   if ( fileheader->Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED ) {
   
      std::cout<<"IMAGE_FILE_LOCAL_SYMS_STRIPPED,";
   }
   
   if ( fileheader->Characteristics & IMAGE_FILE_32BIT_MACHINE ) {
   
      std::cout<<"IMAGE_FILE_32BIT_MACHINE,";
   }
         
   std::cout<<")"<<std::endl;

   if ( fileheader->SizeOfOptionalHeader != sizeof(*optionalheader) ) {

#ifdef _WIN64   
      std::cout<<std::endl<<"PIMAGE_NT_HEADERS64::SizeOfOptionalHeader";
#else   
      std::cout<<std::endl<<"PIMAGE_NT_HEADERS32::SizeOfOptionalHeader";
#endif       

      std::cout<<" and sizeof(*optionalheader) mismatch"<<std::endl;       
   }

#ifdef _WIN64   
   std::cout<<"\nIMAGE_OPTIONAL_HEADER64"<<std::endl;
#else      
   std::cout<<"\nIMAGE_OPTIONAL_HEADER32"<<std::endl;
#endif
   std::cout<<"-----------------------"<<std::endl;
   if ( optionalheader->Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {    
   
      std::cout<<"Magic                                 = 0x"<<std::hex<<optionalheader->Magic<<"(IMAGE_NT_OPTIONAL_HDR32_MAGIC)"<<std::dec<<std::endl;    	  
   } else  if ( optionalheader->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ) {   
   
      std::cout<<"Magic                                 = 0x"<<std::hex<<optionalheader->Magic<<"(IMAGE_NT_OPTIONAL_HDR64_MAGIC)"<<std::dec<<std::endl;     
   }
   else {
   
      std::cout<<"Magic                                 = 0x"<<std::hex<<optionalheader->Magic<<std::dec<<std::endl;     
   }   
   std::cout<<"MajorLinkerVersion.MinorLinkerVersion = "<<(int)optionalheader->MajorLinkerVersion<<"."<<(int)optionalheader->MinorLinkerVersion<<std::endl;
   std::cout<<"SizeOfCode                            = "<<optionalheader->SizeOfCode<<std::endl;
   std::cout<<"AddressOfEntryPoint                   = 0x"<<std::hex<<optionalheader->AddressOfEntryPoint<<std::dec<<std::endl;
   std::cout<<"BaseOfCode                            = 0x"<<std::hex<<optionalheader->BaseOfCode<<std::dec<<std::endl;
   std::cout<<"ImageBase                             = 0x"<<std::hex<<optionalheader->ImageBase<<std::dec<<std::endl;
   std::cout<<"NumberOfRvaAndSizes                   = "<<optionalheader->NumberOfRvaAndSizes<<std::endl;
   
   //epoch(fileheader->TimeDateStamp);
   //epoch(133140 + 59);
   
   return ret;
}	
